package com.gitee.wsl.security.encrypt.sample

import com.gitee.wsl.security.encrypt.Encrypt
import com.gitee.wsl.security.encrypt.StringToStringEncrypt

/**
 * 凯撒密码实现<br></br>
 * 算法来自：https://github.com/zhaorenjie110/SymmetricEncryptionAndDecryption
 *
 * @author looly
 */
class Caesar(val offset: Int = 0): StringToStringEncrypt {

    /**
     * 传入明文，加密得到密文
     *
     * @param src 加密的消息
     * @param offset  偏移量
     * @return 加密后的内容
     */
    override fun encrypt(src: String): String {
        //Assert.notNull(message, "message must be not null!")
        val len = src.length
        val plain = src.toCharArray()
        var c: Char
        for (i in 0..<len) {
            c = src[i]
            if (!c.isLetter()) {
                continue
            }
            plain[i] = encodeChar(c, offset)
        }
        return plain.concatToString()
    }

    /**
     * 传入明文解密到密文
     *
     * @param src 密文
     * @param offset     偏移量
     * @return 解密后的内容
     */
    override fun decrypt(src: String): String {
        //Assert.notNull(cipherText, "cipherText must be not null!")
        val len = src.length
        val plain = src.toCharArray()
        var c: Char
        for (i in 0..<len) {
            c = src[i]
            if (!c.isLetter()) {
                continue
            }
            plain[i] = decodeChar(c, offset)
        }
        return plain.concatToString()
    }

    companion object{
        // 26个字母表
        const val TABLE: String = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"

        // ----------------------------------------------------------------------------------------- Private method start
        /**
         * 加密轮盘
         *
         * @param c      被加密字符
         * @param offset 偏移量
         * @return 加密后的字符
         */
        private fun encodeChar(c: Char, offset: Int): Char {
            val position = (TABLE.indexOf(c) + offset) % 52
            return TABLE[position]
        }

        /**
         * 解密轮盘
         *
         * @param c 字符
         * @return 解密后的字符
         */
        private fun decodeChar(c: Char, offset: Int): Char {
            var position = (TABLE.indexOf(c) - offset) % 52
            if (position < 0) {
                position += 52
            }
            return TABLE[position]
        } // ----------------------------------------------------------------------------------------- Private method end

    }

}

fun Encrypt.Companion.caesar( offset: Int = 0) = Caesar(offset)
